package com.ruoyi.common.elasticsearch.service;

import com.ruoyi.common.elasticsearch.model.EsPageResult;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * Elasticsearch 通用服务接口
 * 定义了 Elasticsearch 操作的核心功能，包括文档增删改查、搜索等
 */
public interface ElasticSearchService {

    /**
     * 保存单条数据
     * @param index 索引名
     * @param id    文档ID
     * @param data  数据对象
     */
    <T> void save(String index, String id, T data);

    /**
     * 批量保存数据
     * @param index   索引名
     * @param dataMap 数据Map, key为ID, value为数据对象
     */
    <T> void bulkSave(String index, Map<String, T> dataMap);

    /**
     * 获取单条数据
     * @param index 索引名
     * @param id    文档ID
     * @param clazz 返回对象的Class
     * @return 文档对象, 如果不存在则返回null
     */
    <T> T get(String index, String id, Class<T> clazz);

    /**
     * 单字段匹配查询 (无分页)
     * @param index  索引名
     * @param field  字段名
     * @param keyword 搜索关键词
     * @param clazz  返回对象的Class
     * @return 文档对象列表
     */
    <T> List<T> search(String index, String field, String keyword, Class<T> clazz) throws IOException;

    /**
     * 单字段匹配查询 (带分页)
     * @param index  索引名
     * @param field  字段名
     * @param keyword 搜索关键词
     * @param page   页码 (从1开始)
     * @param size   每页大小
     * @param clazz  返回对象的Class
     * @return 文档对象列表
     */
    <T> List<T> search(String index, String field, String keyword, int page, int size, Class<T> clazz);

    /**
     * 多字段匹配查询 (无分页，基于 HTTP 原生请求)
     * @param index  索引名
     * @param fields 字段列表
     * @param keyword 搜索关键词
     * @param clazz  返回对象的Class
     * @return 文档对象列表
     */
    <T> List<T> multiSearch(String index, List<String> fields, String keyword, Class<T> clazz) throws IOException;

    /**
     * 多字段匹配查询 (带分页，基于官方客户端)
     * @param index  索引名
     * @param fields 字段列表
     * @param keyword 搜索关键词
     * @param page   页码 (从1开始)
     * @param size   每页大小
     * @param clazz  返回对象的Class
     * @return 文档对象列表
     */
    <T> List<T> multiSearch(String index, List<String> fields, String keyword, int page, int size, Class<T> clazz);

    /**
     * 多字段模糊查询 (无分页)
     * @param index  索引名
     * @param fields 字段列表
     * @param keyword 搜索关键词
     * @param clazz  返回对象的Class
     * @return 文档对象列表
     */
    <T> List<T> fuzzyMultiSearch(String index, List<String> fields, String keyword, Class<T> clazz) throws IOException;

//    /**
//     * 多字段模糊查询 (带分页)
//     * @param index  索引名
//     * @param fields 字段列表
//     * @param keyword 搜索关键词
//     * @param page   页码 (从1开始)
//     * @param size   每页大小
//     * @param clazz  返回对象的Class
//     * @return 文档对象列表
//     */
//    <T> List<T> fuzzyMultiSearch(String index, List<String> fields, String keyword, int page, int size, Class<T> clazz);

    /**
     * 多字段模糊分页查询（带总记录数）
     */
    <T> EsPageResult<T> fuzzyMultiSearchWithTotal(String index, List<String> fields, String keyword,
                                                  int page, int size, Class<T> clazz) throws IOException;
    /**
     * 多字段模糊分页查询 (独立实现)
     * @param index  索引名
     * @param fields 字段列表
     * @param keyword 搜索关键词
     * @param page   页码 (从1开始)
     * @param size   每页大小
     * @param clazz  返回对象的Class
     * @return 文档对象列表
     */
    <T> List<T> fuzzyMultiPageSearch(String index, List<String> fields, String keyword, int page, int size, Class<T> clazz) throws IOException;

    /**
     * 删除单条数据
     * @param index 索引名
     * @param id    文档ID
     */
    void delete(String index, String id);

    /**
     * 判断索引是否存在
     * @param index 索引名
     * @return true 存在, false 不存在
     */
    boolean existsIndex(String index);

    /**
     * 删除索引 (不可逆操作)
     * @param index 索引名
     */
    void deleteIndex(String index);


    /**
     * 单字段精确匹配查询 (无分页)
     * @param index  索引名
     * @param field  字段名
     * @param value  精确匹配值
     * @param clazz  返回对象的Class
     * @return 文档对象列表
     */
    <T> List<T> termSearch(String index, String field, Object value, Class<T> clazz) throws IOException;

    /**
     * 单字段精确匹配查询 (带分页)
     * @param index  索引名
     * @param field  字段名
     * @param value  精确匹配值
     * @param page   页码 (从1开始)
     * @param size   每页大小
     * @param clazz  返回对象的Class
     * @return 文档对象列表
     */
    <T> EsPageResult<T> termSearchWithTotal(String index, String field, Object value,
                                            int page, int size, Class<T> clazz) throws IOException;

    /**
     * 多字段精确匹配查询 (带分页，基于 term 查询)
     * @param index   索引名
     * @param termMap 字段-值映射 (精确匹配)
     * @param page    页码 (从1开始)
     * @param size    每页大小
     * @param clazz   返回对象的Class
     * @return 文档对象列表
     */
    <T> List<T> termSearch(String index, Map<String, Object> termMap, int page, int size, Class<T> clazz) throws IOException;

    /**
     * 多字段精确匹配查询 (带分页和总数)
     * @param index   索引名
     * @param termMap 字段-值映射 (精确匹配)
     * @param page    页码 (从1开始)
     * @param size    每页大小
     * @param clazz   返回对象的Class
     * @return 包含分页信息和总数的结果
     */
    <T> EsPageResult<T> termSearchWithTotal(String index, Map<String, Object> termMap,
                                            int page, int size, Class<T> clazz) throws IOException;

    /**
     * 嵌套查询 (针对nested类型字段)
     * @param index 索引名
     * @param path 嵌套路径 (如"addresses")
     * @param field 嵌套字段名
     * @param keyword 搜索关键词
     * @param page 页码 (从1开始)
     * @param size 每页大小
     * @param clazz 返回对象的Class
     * @return 包含分页信息和总数的结果
     */
    <T> EsPageResult<T> nestedSearch(String index, String path, String field,
                                     String keyword, int page, int size, Class<T> clazz) throws IOException;

    /**
     * 复杂嵌套查询 (支持多个条件)
     * @param index 索引名
     * @param path 嵌套路径
     * @param nestedQuery 嵌套查询条件
     * @param page 页码 (从1开始)
     * @param size 每页大小
     * @param clazz 返回对象的Class
     * @return 包含分页信息和总数的结果
     */
    <T> EsPageResult<T> nestedSearch(String index, String path, Query nestedQuery,
                                     int page, int size, Class<T> clazz) throws IOException;

//    <T> EsPageResult<T> executeNestedSearch(String index, Query query,
//                                                    int page, int size, Class<T> clazz) throws IOException;
    <T> EsPageResult<T> nestedTermSearch(String index, String path, String field,
                                     Object value, int page, int size, Class<T> clazz) throws IOException;

    <T> EsPageResult<T> nestedFuzzySearch(String index, String path, String field,
                                          String keyword, int page, int size, Class<T> clazz) throws IOException;
}